package com.hsogoo.collate.configuration;

import com.hsogoo.collate.batch.*;
import com.hsogoo.collate.domain.CollateFieldsDO;
import com.hsogoo.collate.mapper.CollateFieldsMapper;
import com.hsogoo.collate.mapper.CollateRecordMapper;
import com.hsogoo.collate.mapper.DynamicMapper;
import com.hsogoo.collate.redis.RedisClient;
import com.hsogoo.collate.service.CollateDownloadService;
import com.hsogoo.collate.service.AsyncDynamicQueryService;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.ClassPathResource;

/**
 * @Author huangsaigang
 * Created @2019-10-28.
 */
@Configuration
@EnableBatchProcessing
public class BatchConfig {

    @Autowired
    private JobBuilderFactory jobs;             //用于构建job
    @Autowired
    private StepBuilderFactory steps;           //用于构建step
    @Autowired
    private CollateDownloadService downloadService;
    @Autowired
    private CollateFieldsMapper collateFieldsMapper;
    @Autowired
    private AsyncDynamicQueryService asyncDynamicQueryService;
    @Autowired
    private RedisClient redisClient;



    @Bean
    @Scope("prototype")
    public CollateFields collateFields(){
        return new CollateFields();
    }

    @Bean
    public BeanWrapperFieldSetMapper fieldSetMapper(){
        BeanWrapperFieldSetMapper fieldSetMapper = new BeanWrapperFieldSetMapper();
        fieldSetMapper.setPrototypeBeanName("collateFields");
        return fieldSetMapper;
    }

    @Bean
    public DownloadCollateFileTasklet downloadCollateFileTasklet(){
        DownloadCollateFileTasklet downloadCollateFileTasklet = new DownloadCollateFileTasklet();
        downloadCollateFileTasklet.setDownloadService(downloadService);
        return downloadCollateFileTasklet;
    }
    /**
     * 下载对账文件
     * @return
     */
    @Bean
    public Step downloadCollateFile(DownloadCollateFileTasklet downloadCollateFileTasklet){
        return steps.get("downloadCollateFile")
                .tasklet(downloadCollateFileTasklet)
                .build();
    }

    @Bean
    public RecordCollateTasklet recordCollateTasklet(CollateRecordMapper collateRecordMapper){
        RecordCollateTasklet recordCollateTasklet = new RecordCollateTasklet();
        recordCollateTasklet.setCollateRecordMapper(collateRecordMapper);
        return recordCollateTasklet;
    }

    /**
     * 记录对账，幂等
     * @return
     */
    @Bean
    public Step recordCollate(){
        return steps.get("recordCollate")
                .tasklet(recordCollateTasklet(null))
                .build();
    }

    @Bean
    @StepScope
    public FlatFileItemReader<CollateFields> collateReader(@Value("#{jobParameters[targetFieldMapper]}") String targetFieldMapper,
                                                           @Value("#{jobParameters[targetFieldSeparator]}") String targetFieldSeparator,
                                                           @Value("#{jobParameters[localFilePath]}") String localFilePath){
        FlatFileItemReader<CollateFields> collateReader = new FlatFileItemReader();

//        collateReader.setResource(new FileSystemResource(localFilePath));
        collateReader.setResource(new ClassPathResource("test.txt"));

        String[] targetFields = targetFieldMapper.split(",");
        String[] targetFieldsName = new String[targetFields.length];
        for (int i = 0; i < targetFields.length;) {
            targetFieldsName[i] = "field" + (++i);
        }
        DefaultLineMapper<CollateFields> lineMapper = new DefaultLineMapper();
        DelimitedLineTokenizer delimitedLineTokenizer = new DelimitedLineTokenizer();
        delimitedLineTokenizer.setDelimiter(targetFieldSeparator);
        delimitedLineTokenizer.setNames(targetFieldsName);
        lineMapper.setLineTokenizer(delimitedLineTokenizer);
        CollateFieldSetMapper collateFieldSetMapper = new CollateFieldSetMapper();
        lineMapper.setFieldSetMapper(collateFieldSetMapper);
        collateReader.setLineMapper(lineMapper);

        return collateReader;
    }

    @Bean
    @StepScope
    public CollateProcessor collateProcessor(@Value("#{jobParameters[taskName]}") String taskName,
                                             @Value("#{jobParameters[targetCollateDate]}") String targetCollateDate,
                                             @Value("#{jobExecutionContext[recordId]}") Long recordId ){
        CollateProcessor collateProcessor = new CollateProcessor(taskName, targetCollateDate, recordId);
        return collateProcessor;
    }

    @Bean
    @StepScope
    public CollateWriter collateWriter(CollateFieldsMapper collateFieldsMapper){
        CollateWriter collateWriter = new CollateWriter();
        collateWriter.setCollateFieldsMapper(collateFieldsMapper);
        return collateWriter;
    }

    /**
     * 解析入库
     * @return
     */
    @Bean
    public Step persistCollateFile(){
        return steps.get("persistCollateFile")
                .<CollateFields, CollateFieldsDO> chunk(1)
                .reader(collateReader(null,null, null))
                .processor(collateProcessor(null, null, null))
                .writer(collateWriter(null))
                .build();
    }

    @Bean
    public DoCollateTasklet doCollateTasklet(){
        DoCollateTasklet doCollateTasklet = new DoCollateTasklet();
        doCollateTasklet.setCollateFieldsMapper(collateFieldsMapper);
        doCollateTasklet.setAsyncDynamicQueryService(asyncDynamicQueryService);
        doCollateTasklet.setRedisClient(redisClient);
        return doCollateTasklet;
    }

    /**
     * 对账
     * @return
     */
    @Bean
    public Step doCollate(){
        return steps.get("doCollate")
                .tasklet(doCollateTasklet())
                .build();
    }

    @Bean
    public Job collateJob(){
        return jobs.get("collateJob")
                .incrementer(new RunIdIncrementer())
                .start(downloadCollateFile(null))
                .next(recordCollate())
                .next(persistCollateFile())
                .next(doCollate())
                .build();
    }

}
